package cate.game.res.holy_pet;

import cate.common.table.d.GD;
import cate.common.table.res.holy_pet.adventure.HolyPetAdventureRow;
import cate.common.table.res.holy_pet.scene_spot.HolyPetSceneSpotRow;
import cate.common.table.res.holy_pet.scene_spot.HolyPetSceneSpotRow.AdventureRWItem;
import cate.common.util.GameResult;
import cate.common.util.TimeTool;
import cate.common.util.random.RWList;
import cate.game.db.facade.KvLoader;
import cate.game.db.mongo.kv.KvMongo;
import cate.game.framework.ModuleMan;
import cate.game.framework.ThreadShare;
import cate.game.res.MixRes;
import cate.game.res.holy_pet.core.HolyPetRoleMission;
import cate.game.res.holy_pet.core.HolyPetSPO;
import cate.game.res.holy_pet.core.HolyPetSingleMission;
import cate.game.role.Role;
import cate.game.role.res.holy_pet.core.HolyPetAdventureLog;
import cate.game.role.res.holy_pet.core.HolyPetRoleMissionVO;
import cate.game.role.res.holy_pet.core.SingleScenePO;
import easy.java.dev.note.NoteField;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 灵宠全服管理
 *
 * @author ShenSL
 * @since 2023/8/24 22:25
 */
public class HolyPetManager extends ModuleMan {
    @NoteField("全服数据")
    public HolyPetSPO data;

    @Override
    public void initDependent() throws Exception {
        data = new KvLoader<>(game, HolyPetSPO.class, KvMongo.KEY_HOLY_PET).getBySrvId();
        // 加载常量
        HolyPetConstants.loadFromTable(game.table.common);
    }

    @Override
    public void shutdown() {
        super.shutdown();
        game.db.kv.save(data);
    }

    /**
     * 循环
     */
    public synchronized void tick() {
        long nowTime = System.currentTimeMillis();
        // 结算检测
        data.roleMissionMap.values().forEach(rm -> {
            Iterator<Map.Entry<Integer, HolyPetSingleMission>> iter = rm.missions.entrySet().iterator();
            while (iter.hasNext()) {
                Map.Entry<Integer, HolyPetSingleMission> entry = iter.next();
                HolyPetSingleMission mission = entry.getValue();
                if (entry.getValue().getEndTime() <= nowTime) {
                    Role role = game.role.getRole(rm.uid);
                    if (role != null) {
                        if (role.getStatus().isOnline()) {
                            ThreadShare.instance().exe(role, () -> {
                                SingleScenePO scenePO = role.getRes().holyPet.scenes.get(mission.getSceneId());
                                if (scenePO != null) {
                                    scenePO.setReward(mission.getReward());
                                }
                                role.getRes().holyPet.noticeUpdate();
                            });
                        } else {
                            SingleScenePO scenePO = role.getRes().holyPet.scenes.get(mission.getSceneId());
                            if (scenePO != null) {
                                scenePO.setReward(mission.getReward());
                            }
                        }
                    }
                    iter.remove();
                    broadcastMissionChange(rm.uid);
                }
            }
        });
        // 移除任务全部完成的项
        data.roleMissionMap.entrySet().removeIf(entry -> entry.getValue().missions.isEmpty());
        // 触发事件
        data.roleMissionMap.values().forEach(rm -> rm.missions.values().forEach(mission -> {
            if (mission.getNextTriggerTime() <= nowTime) {
                HolyPetSceneSpotRow spotRow = game.table.holyPet.scene_spot.getRow(mission.getSceneId(), mission.getPlaceId());
                if (spotRow != null) {
                    if (new Random().nextInt(GD.W_10000) <= spotRow.adventureProb) {
                        RWList<AdventureRWItem> rwList = new RWList<>();
                        rwList.setup(spotRow.items.stream()
                                .filter(item -> mission.available(item.adventureId))
                                .collect(Collectors.toList()));
                        int adventureId = Optional.ofNullable(rwList.get())
                                .map(item -> item.adventureId)
                                .orElse(0);
                        if (adventureId != 0) {
                            mission.addAdventure(adventureId);
                            HolyPetAdventureLog log = HolyPetAdventureLog.TRIGGER(mission.getPlaceId(), mission.getPetId(), adventureId);
                            Role role = game.role.getRoleFromActive(rm.uid);
                            if (role != null && role.getStatus().isOnline()) {
                                role.getRes().holyPet.addAdventureLog(log);
                            } else {
                                addCacheLog(rm.uid, log);
                            }
                        }
                        broadcastMissionChange(rm.uid);
                    }
                    mission.setNextTriggerTime(nowTime + spotRow.adventureDurationSec * TimeTool.TimeCons.SECOND);
                }
            }
        }));
    }

    /**
     * 添加个人任务
     *
     * @param role    玩家
     * @param mission 任务
     */
    public synchronized void addRoleMission(Role role, HolyPetSingleMission mission) {
        HolyPetSceneSpotRow spotRow = game.table.holyPet.scene_spot.getRow(mission.getSceneId(), mission.getPlaceId());
        if (spotRow == null) {
            return;
        }
        HolyPetRoleMission roleMission = data.roleMissionMap.computeIfAbsent(role.getUid(), (uid) -> {
            HolyPetRoleMission rm = new HolyPetRoleMission();
            rm.uid = uid;
            rm.missions = new HashMap<>();
            return rm;
        });
        mission.setNextTriggerTime(mission.getStartTime() + spotRow.adventureDurationSec * TimeTool.TimeCons.SECOND);
        roleMission.missions.put(mission.getSceneId(), mission);
        broadcastMissionChange(role.getUid());
    }

    /**
     * 发起协助
     *
     * @param role        发起玩家
     * @param targetUid   目标UID
     * @param sceneId     场景ID
     * @param adventureId 事件ID
     * @return
     */
    public synchronized GameResult<MixRes> support(Role role, String targetUid, int sceneId, int adventureId) {
        GameResult<MixRes> r = new GameResult<>();
        HolyPetRoleMission rm = data.roleMissionMap.get(targetUid);
        if (rm == null || !rm.missions.containsKey(sceneId)) {
            return r.fail("派遣任务不存在");
        }
        HolyPetSingleMission mission = rm.missions.get(sceneId);
        if (mission.getAdventures() == null || !mission.getAdventures().contains(adventureId)) {
            return r.fail("奇遇事件已完成");
        }
        HolyPetSceneSpotRow spotRow = game.table.holyPet.scene_spot.getRow(sceneId, mission.getPlaceId());
        if (spotRow == null) {
            return r.fail("配置出错了");
        }
        HolyPetAdventureRow adventureRow = game.table.holyPet.adventure.get(adventureId);
        if (adventureRow == null) {
            return r.fail("配置出错咧");
        }
        mission.getAdventures().removeIf(i -> i == adventureId);
        mission.addDone(adventureId);
        mission.getReward().addList(new MixRes(adventureRow.rewardStr));
        r.data = new MixRes(spotRow.supportRewardStr);
        HolyPetAdventureLog log = HolyPetAdventureLog.HELP(mission.getPlaceId(), mission.getPetId(), adventureId, role);
        Role oppo = game.role.getRoleFromActive(targetUid);
        if (oppo != null && oppo.getStatus().isOnline()) {
            oppo.getRes().holyPet.addAdventureLog(log);
        } else {
            addCacheLog(targetUid, log);
        }
        return r.success();
    }

    /**
     * 添加缓存日志
     *
     * @param roleUid 玩家唯一ID
     * @param log     日志
     */
    private void addCacheLog(String roleUid, HolyPetAdventureLog log) {
        List<HolyPetAdventureLog> roleLogs = data.cachedLogs.computeIfAbsent(roleUid, (uid) -> new ArrayList<>());
        roleLogs.add(log);
    }

    /**
     * 广播协助列表变更
     *
     * @param uid 任务主体UID
     */
    private void broadcastMissionChange(String uid) {
        game.role.activeForOnline(role -> {
            if (!role.getRes().holyPet.isOpen()) {
                return;
            }
            if (role.getFriend().getFriend(uid) == null) {
                return;
            }
            role.getRes().holyPet.noticeSupport();
        });
    }

    /**
     * 获取支援列表
     *
     * @param role 玩家
     */
    public List<HolyPetRoleMissionVO> getSupportList(Role role) {
        return data.roleMissionMap.values().stream().filter(rm -> role.getFriend().getFriend(rm.uid) != null)
                .map(rm -> new HolyPetRoleMissionVO(role.getFriend().getFriend(rm.uid).it, rm.missions))
                .collect(Collectors.toList());
    }

    /**
     * 获取并移除玩家缓存日志
     *
     * @param roleUid 玩家UID
     */
    public synchronized List<HolyPetAdventureLog> getAndDropCachedLogs(String roleUid) {
        return data.cachedLogs.remove(roleUid);
    }
}
